#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <SDL/SDL.h>

#include "zombies.h"
#include "primitives.h"
#include "display.h"
#include "monsters.h"
#include "victims.h"  // due to one time monsters
#include "level.h"

// monsters
monster_t rmonsters[MAX_MONSTERS];
victim_t fmonsters[MAX_MONSTERS];

int rmonstercount; // respawn
int fmonstercount; // fixed

// sprites surface
SDL_Surface *monstersprites;

// monster names, aligned to sprites
struct names_t
{
    int code;
    const char *name;
}monstername[]=
{
    // normal monsters
    { 0x8187F8, "Normal Zombie" },
    { 0x81B2B0, "Axe Baby"      },
    { 0x81B664, "Flame Baby"    },
    { 0x81ABF5, "WereWolf"      },
    { 0x818C17, "Mummy"         },
    { 0x81D2F9, "Alien Plant"   },
    { 0x818E3F, "Clone Plant"   },
    { 0x818E89, "Clone Plant 2" },
    { 0x81C87B, "Football"      },
    { 0x81983A, "Chainsaw"      },
    { 0x8199DF, "Martian"       },
    { 0x81CCCF, "Blob"          },
    { 0x81E51A, "Squidman"      },
    { 0x81D704, "Mushroom Man"  },
    { 0x82EF36, "Vampire"       },
    { 0x82990F, "Tentacle"      },
    { 0x81A455, "Frankenstein"  },
    { 0x83B55E, "Dr. Tongue"    },
    { 0x83B277, "Spider"        },
    { 0x81C1FB, "Blue Ant"      },
    { 0x81C28C, "Blue Ant 2"    },
    
    // fast monsters, means that it will chase
    // you as soon as it spawns. The monster
    // will not stay wandering around
    { 0x8188CA, "Fast Zombie"        },
    { 0x81C321, "Fast Blue Ant"      },
    { 0x81C3B6, "Fast Red Ant"       },
    { 0x819A3E, "Fast Martian"       },
    { 0x818F1F, "Fast Clone Plant"   },
    { 0x81D2F1, "Fast Alien Plant"   },
    { 0x81E481, "Fast Squidman"      },
    
    // Other types
    { 0x82F25D, "Fire"    },
    
    // Credit level heads
    { 0x83B7F6, "Big Head"     },
    { 0x82DD52, "Credit Heads" }
};

const char *getmonstername(int code)
{
    int i;
    for(i=0;i<sizeof(monstername)/8;i++)
        if(code==monstername[i].code)
            return monstername[i].name;
   
    return "ERROR";
}

int getmonsteroffset(int code)
{
    int i;
    for(i=0;i<sizeof(monstername)/8;i++)
        if(code==monstername[i].code)
            return i;
    
    printf("Monster Code not found: 0x%02x\n",code);
    return 0;
}

int monsterclicked(int x, int y)
{
    int i;
    
    // respawn
    for(i=0;i<rmonstercount;i++)
    {
        if(x>rmonsters[i].x-24 && x<(rmonsters[i].x+24) && y>rmonsters[i].y-24 && y<(rmonsters[i].y+24))
            return i;
    }

    // non-respawn
    for(i=0;i<fmonstercount;i++)
    {
        if(x>fmonsters[i].x-24 && x<(fmonsters[i].x+24) && y>fmonsters[i].y-24 && y<(fmonsters[i].y+24))
            return i|(1<<8);
    }

    return -1;
}

void dragmonster(int id, int x, int y)
{
    if(id>>8)
    {
        id&=~(1<<8);  // remove flag
        fmonsters[id].x+=x;
        fmonsters[id].y+=y;
    }
    else
    {
        rmonsters[id].x+=x;
        rmonsters[id].y+=y;
    }
}

void readmonsters()
{
    unsigned int offset;
    int r;

    // respawning monsters
    r=level.victim_ptr-level.monster_ptr;
	if(r>2)
	{
		offset=BASE_PTR+level.monster_ptr;

		rmonstercount=(r-2)/sizeof(monster_t);
        memset(&rmonsters,0,sizeof(monster_t)*MAX_MONSTERS);
        memcpy(&rmonsters,romdata+offset,sizeof(monster_t)*rmonstercount);
	}
	else
        rmonstercount=0;

    // non-respawning monsters
    offset=level.item_ptr-level.victim_ptr;
    r=sizeof(victim_t)*MAX_VICTIMS+2;
    if(offset>r)
	{
        offset=BASE_PTR+level.victim_ptr+(r-2);
        r=level.item_ptr-(level.victim_ptr+(r-2));

        fmonstercount=(r-2)/sizeof(victim_t);
        memset(&fmonsters,0,sizeof(victim_t)*MAX_MONSTERS);
        memcpy(&fmonsters,romdata+offset,sizeof(victim_t)*fmonstercount);
	}
	else
		fmonstercount=0;
}

void drawmonsters()
{
    SDL_Rect src,dst;
    int i;

    // monsters layer sizes
    src.w=dst.w=48;
    src.h=dst.h=58;
   
    // respwanable monsters
    for(i=0;i<rmonstercount;i++)
    {
		src.x=48*getmonsteroffset(rmonsters[i].code);
		src.y=0;
        
        // align to layer size
        dst.x=rmonsters[i].x-bgoffset.x-24;
        dst.y=rmonsters[i].y-bgoffset.y-48;

        // let SDL handle clipping
        SDL_BlitSurface(monstersprites,&src,screen,&dst);

        if(!mouse.drag)
        {
            if(rmonsters[i].radius>0)
                SDL_DrawCircle(screen,rmonsters[i].x-bgoffset.x,rmonsters[i].y-bgoffset.y,rmonsters[i].radius>>1,0x00ff00);
        }
    }
    
    // non-respwanable monsters
    for(i=0;i<fmonstercount;i++)
    {
		src.x=48*getmonsteroffset(fmonsters[i].code);
		src.y=0;
        
        // align to layer sizes
        dst.x=fmonsters[i].x-bgoffset.x-24;
        dst.y=fmonsters[i].y-bgoffset.y-58;

        // let SDL handle clipping
        SDL_BlitSurface(monstersprites,&src,screen,&dst);
    }
}

void initmonsters()
{
    SDL_Surface *temp;
    
    temp=SDL_LoadBMP("monsters.bmp");
    monstersprites=SDL_ConvertSurface(temp,screen->format,SDL_SWSURFACE);
    SDL_FreeSurface(temp);

    // apply color mask
    SDL_SetColorKey(monstersprites,SDL_SRCCOLORKEY,0xff00ff);
}